//MODUL STACK }
//Deklarasi stack yang diimplementasi dengan list linier }
//dengan representasi fisik pointer }
//TOP adalah alamat elemen puncak }

#include "stack.h"

// ********* Prototype **********

// *** Konstruktor/Kreator ***
void CreateEmpty (Stack * S)
/* I.S. sembarang */
/* F.S. Membuat sebuah stack S yang kosong */
{	Top(*S) = Nil;
}

// *** Prototype manajemen memori ***
void Alokasi (address *P, infotype X)
/* I.S. Sembarang */
/* F.S. Alamat P dialokasi, jika berhasil maka Info(P)=X dan
        Next(P)=Nil */
/*P=Nil jika alokasi gagal */
{	*P = (address) malloc (sizeof(ElmtStack));
	if (*P != Nil) {
		Info(*P).x = X.x;
		Info(*P).y = X.y;
		Next(*P) = Nil;
	} else
		*P = Nil;
}

void Dealokasi (address *P)
/* I.S. P adalah hasil alokasi, P <> Nil */
/* F.S. Alamat P didealokasi, dikembalikan ke sistem */
{	free(*P);
}

// ********* Predikat Untuk test keadaan KOLEKSI **********
boolean IsEmpty (Stack S)
/* Mengirim true jika Stack kosong: TOP(S) = Nil */
{	return (Top(S) == Nil);
}

// boolean IsFull(Stack S)
// // Mengirim true jika tabel penampung nilai elemen stack penuh 
// {	return FALSE;
// }

// ********** Operator Dasar Stack ********* 
void Push (Stack * S, infotype X)
/* Menambahkan X sebagai elemen Stack S */
/* I.S. S mungkin kosong, X terdefinisi */
/* F.S. X menjadi TOP yang baru jika alokasi X berhasil, */
/*jika tidak, S tetap */
/* Pada dasarnya adalah operasi Insert First pada list linier */
{	address P;
	Alokasi(&P,X);
	if (P != Nil) {
		Next(P) = Top(*S);
		Top(*S) = P;
	}
}

void PushUnik (Stack * S, infotype X){
	boolean found = FALSE;
	address P, Pcurr;
	Alokasi(&P,X);
	Pcurr = Top(*S);
	if (P != Nil){
		while(Pcurr != Nil && !found){
			if (Info(Pcurr).x==Info(P).x && Info(Pcurr).y==Info(P).y){
				found = TRUE;
				break;
			}
			Pcurr = Next(Pcurr);
		}
		if (!found){
			Next(P) = Top(*S);
			Top(*S) = P;
		}
	}
}

void Pop (Stack * S, infotype * X)
/* Menghapus X dari Stack S. */
/* I.S. S tidak mungkin kosong */
/* F.S. X adalah nilai elemen TOP yang lama, */
/*elemen TOP yang lama didealokasi */
/* Pada dasarnya adalah operasi Delete First pada list linier */
{	address P;
	*X = InfoTop(*S);
	P = Top(*S);
	Top(*S) = Next(Top(*S));
	Next(P) = Nil;
	Dealokasi(&P);
}

int NbElmt(Stack S) {
	int count = 0;
	address P;
	if (!IsEmpty(S)) {
		P = Top(S);
		while (Next(P) != Nil) {
			count++;
			P = Next(P);
		}
		count++;
	}
	return count;
}

boolean Contains(Stack S,infotype X) {
	int found = FALSE;
	address P;
	if (!IsEmpty(S)) {
		P = Top(S);
		while (P != Nil) {
			if (Info(P).x == X.x && Info(P).y == X.y) {
				found = TRUE;
				break;
			}
			P = Next(P);
		}
	}
	return found;
}

boolean PushFill(Stack * S, infotype X) {
	address P;
	Alokasi(&P,X);
	if (P != Nil) {
		Next(P) = Top(*S);
		Top(*S) = P;
		return TRUE;
	}
	return FALSE;
}
boolean PopFill(Stack * S, infotype * X) {
	if (!IsEmpty(*S)) {
		address P;
		*X = InfoTop(*S);
		P = Top(*S);
		Top(*S) = Next(Top(*S));
		Next(P) = Nil;
		Dealokasi(&P);
		return TRUE;
	}
	return FALSE;
}